// Copyright (c) Microsoft Corporation.  All Rights Reserved.  See License.txt in the project root for license information.

namespace Microsoft.FSharp.Collections

    open System
    open Microsoft.FSharp.Core
    open Microsoft.FSharp.Collections
    open System.Collections.Generic

    /// <summary>Basic operations on arrays.</summary>
    [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
    [<RequireQualifiedAccess>]
    module Array = 

        /// <summary>Builds a new array that contains the cartesian product of the two input arrays.</summary>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when either of the input arrays is null.</exception>
        /// <returns>The resulting array of pairs.</returns>
        [<CompiledName("AllPairs")>]
        val allPairs: array1:'T1[] -> array2:'T2[] -> ('T1 * 'T2)[]

        /// <summary>Builds a new array that contains the elements of the first array followed by the elements of the second array.</summary>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        /// <returns>The resulting array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when either of the input arrays is null.</exception>
        [<CompiledName("Append")>]
        val append: array1:'T[] -> array2:'T[] -> 'T[]

        /// <summary>Returns the average of the elements in the array.</summary>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentException">Thrown when <c>array</c> is empty.</exception>
        /// <returns>The average of the elements in the array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Average")>]
        val inline average   : array:^T[] -> ^T   
                                 when ^T : (static member ( + ) : ^T * ^T -> ^T) 
                                 and  ^T : (static member DivideByInt : ^T*int -> ^T) 
                                 and  ^T : (static member Zero : ^T)


        /// <summary>Returns the average of the elements generated by applying the function to each element of the array.</summary>
        /// <param name="projection">The function to transform the array elements before averaging.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentException">Thrown when <c>array</c> is empty.</exception>
        /// <returns>The computed average.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("AverageBy")>]
        val inline averageBy   : projection:('T -> ^U) -> array:'T[] -> ^U   
                                    when ^U : (static member ( + ) : ^U * ^U -> ^U) 
                                    and  ^U : (static member DivideByInt : ^U*int -> ^U) 
                                    and  ^U : (static member Zero : ^U)
                                    
        /// <summary>Reads a range of elements from the first array and write them into the second.</summary>
        /// <param name="source">The source array.</param>
        /// <param name="sourceIndex">The starting index of the source array.</param>
        /// <param name="target">The target array.</param>
        /// <param name="targetIndex">The starting index of the target array.</param>
        /// <param name="count">The number of elements to copy.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when either of the input arrays is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when any of sourceIndex, targetIndex or count are negative,
        /// or when there aren't enough elements in source or target.</exception>
        [<CompiledName("CopyTo")>]
        val inline blit: source:'T[] -> sourceIndex:int -> target:'T[] -> targetIndex:int -> count:int -> unit
        
        /// <summary>For each element of the array, applies the given function. Concatenates all the results and return the combined array.</summary>
        /// <param name="mapping">The function to create sub-arrays from the input array elements.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The concatenation of the sub-arrays.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Collect")>]
        val collect : mapping:('T -> 'U[]) -> array:'T[] -> 'U[]

        /// <summary>Compares two arrays using the given comparison function, element by element.</summary>
        ///
        /// <param name="comparer">A function that takes an element from each array and returns an int.
        /// If it evaluates to a non-zero value iteration is stopped and that value is returned.</param>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        ///
        /// <returns>Returns the first non-zero result from the comparison function. If the first array has 
        /// a larger element, the return value is always positive. If the second array has a larger 
        /// element, the return value is always negative. When the elements are equal in the two 
        /// arrays, 1 is returned if the first array is longer, 0 is returned if they are equal in 
        /// length, and -1 is returned when the second array is longer.</returns>
        ///
        /// <exception cref="System.ArgumentNullException">Thrown when either of the input arrays
        /// is null.</exception>
        [<CompiledName("CompareWith")>]
        val inline compareWith: comparer:('T -> 'T -> int) -> array1:'T[] -> array2:'T[] -> int

        /// <summary>Builds a new array that contains the elements of each of the given sequence of arrays.</summary>
        /// <param name="arrays">The input sequence of arrays.</param>
        /// <returns>The concatenation of the sequence of input arrays.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input sequence is null.</exception>
        [<CompiledName("Concat")>]
        val concat: arrays:seq<'T[]> -> 'T[]
        
        /// <summary>Tests if the array contains the specified element.</summary>
        /// <param name="value">The value to locate in the input array.</param>
        /// <param name="array">The input array.</param>
        /// <returns>True if the input array contains the specified element; false otherwise.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Contains")>]
        val inline contains: value:'T -> array:'T[] -> bool when 'T : equality

        /// <summary>Builds a new array that contains the elements of the given array.</summary>
        /// <param name="array">The input array.</param>
        /// <returns>A copy of the input array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Copy")>]
        val copy: array:'T[] -> 'T[]

        /// <summary>Applies a key-generating function to each element of an array and returns an array yielding unique
        /// keys and their number of occurrences in the original array.</summary>
        ///
        /// <param name="projection">A function transforming each item of the input array into a key to be
        /// compared against the others.</param>
        /// <param name="array">The input array.</param>
        ///
        /// <returns>The result array.</returns>
        ///
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("CountBy")>]
        val countBy : projection:('T -> 'Key) -> array:'T[] -> ('Key * int)[] when 'Key : equality

        /// <summary>Creates an array whose elements are all initially the given value.</summary>
        /// <param name="count">The length of the array to create.</param>
        /// <param name="value">The value for the elements.</param>
        /// <returns>The created array.</returns>
        /// <exception cref="System.ArgumentException">Thrown when count is negative.</exception>
        [<CompiledName("Create")>]
        val create: count:int -> value:'T -> 'T[]

        /// <summary>Returns the first element of the array, or
        /// <c>None</c> if the array is empty.</summary>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <returns>The first element of the array or None.</returns>
        [<CompiledName("TryHead")>]
        val tryHead: array:'T[] -> 'T option
         
        /// <summary>Applies the given function to successive elements, returning the first
        /// result where function returns <c>Some(x)</c> for some <c>x</c>. If the function 
        /// never returns <c>Some(x)</c> then <c>None</c> is returned.</summary>
        /// <param name="chooser">The function to transform the array elements into options.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The first transformed element that is <c>Some(x)</c>.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("TryPick")>]
        val tryPick: chooser:('T -> 'U option) -> array:'T[] -> 'U option

        /// <summary>Fills a range of elements of the array with the given value.</summary>
        /// <param name="target">The target array.</param>
        /// <param name="targetIndex">The index of the first element to set.</param>
        /// <param name="count">The number of elements to set.</param>
        /// <param name="value">The value to set.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when either targetIndex or count is negative.</exception>
        [<CompiledName("Fill")>]
        val fill: target:'T[] -> targetIndex:int -> count:int -> value:'T -> unit

        /// <summary>Applies the given function to successive elements, returning the first
        /// result where function returns <c>Some(x)</c> for some <c>x</c>. If the function 
        /// never returns <c>Some(x)</c> then <c>KeyNotFoundException</c> is raised.</summary>
        /// <param name="chooser">The function to generate options from the elements.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.Collections.Generic.KeyNotFoundException">Thrown if every result from
        /// <c>chooser</c> is <c>None</c>.</exception>
        /// <returns>The first result.</returns>
        [<CompiledName("Pick")>]
        val pick: chooser:('T -> 'U option) -> array:'T[] -> 'U 

        /// <summary>Applies the given function to each element of the array. Returns
        /// the array comprised of the results "x" for each element where
        /// the function returns Some(x)</summary>
        /// <param name="chooser">The function to generate options from the elements.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The array of results.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Choose")>]
        val choose: chooser:('T -> 'U option) -> array:'T[] -> 'U[]

        /// <summary>Divides the input array into chunks of size at most <c>chunkSize</c>.</summary>
        /// <param name="chunkSize">The maximum size of each chunk.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The array divided into chunks.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when <c>chunkSize</c> is not positive.</exception>
        [<CompiledName("ChunkBySize")>]
        val chunkBySize: chunkSize:int -> array:'T[] -> 'T[][]

        /// <summary>Returns an array that contains no duplicate entries according to generic hash and
        /// equality comparisons on the entries.
        /// If an element occurs multiple times in the array then the later occurrences are discarded.</summary>
        ///
        /// <param name="array">The input array.</param>
        ///
        /// <returns>The result array.</returns>
        ///
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Distinct")>]
        val distinct: array:'T[] -> 'T[] when 'T : equality

        /// <summary>Returns an array that contains no duplicate entries according to the 
        /// generic hash and equality comparisons on the keys returned by the given key-generating function.
        /// If an element occurs multiple times in the array then the later occurrences are discarded.</summary>
        ///
        /// <param name="projection">A function transforming the array items into comparable keys.</param>
        /// <param name="array">The input array.</param>
        ///
        /// <returns>The result array.</returns>
        ///
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("DistinctBy")>]
        val distinctBy: projection:('T -> 'Key) -> array:'T[] -> 'T[] when 'Key : equality

        /// <summary>Splits the input array into at most <c>count</c> chunks.</summary>
        /// <param name="count">The maximum number of chunks.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The array split into chunks.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when <c>count</c> is not positive.</exception>
        [<CompiledName("SplitInto")>]
        val splitInto: count:int -> array:'T[] -> 'T[][]

        /// <summary>Returns an empty array of the given type.</summary>
        /// <returns>The empty array.</returns>
        [<GeneralizableValue>]
        [<CompiledName("Empty")>]
        val empty<'T> : 'T[]

        /// <summary>Returns the only element of the array.</summary>
        ///
        /// <param name="array">The input array.</param>
        ///
        /// <returns>The only element of the array.</returns>
        ///
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input does not have precisely one element.</exception>
        [<CompiledName("ExactlyOne")>]
        val exactlyOne: array:'T[] -> 'T

        /// <summary>Returns a new list with the distinct elements of the input array which do not appear in the itemsToExclude sequence,
        /// using generic hash and equality comparisons to compare values.</summary>
        ///
        /// <param name="itemsToExclude">A sequence whose elements that also occur in the input array will cause those elements to be
        /// removed from the result.</param>
        /// <param name="array">An array whose elements that are not also in itemsToExclude will be returned.</param>
        ///
        /// <returns>An array that contains the distinct elements of <c>array</c> that do not appear in <c>itemsToExclude</c>.</returns>
        ///
        /// <exception cref="System.ArgumentNullException">Thrown when either itemsToExclude or array is null.</exception>
        [<CompiledName("Except")>]
        val except: itemsToExclude:seq<'T> -> array:'T[] -> 'T[] when 'T : equality

        /// <summary>Tests if any element of the array satisfies the given predicate.</summary>
        ///
        /// <remarks>The predicate is applied to the elements of the input array. If any application 
        /// returns true then the overall result is true and no further elements are tested. 
        /// Otherwise, false is returned.</remarks>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <returns>True if any result from <c>predicate</c> is true.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Exists")>]
        val exists: predicate:('T -> bool) -> array:'T[] -> bool

        /// <summary>Tests if any pair of corresponding elements of the arrays satisfies the given predicate.</summary>
        ///
        /// <remarks>The predicate is applied to matching elements in the two collections up to the lesser of the 
        /// two lengths of the collections. If any application returns true then the overall result is 
        /// true and no further elements are tested. Otherwise, if one collections is longer 
        /// than the other then the <c>ArgumentException</c> exception is raised. 
        /// Otherwise, false is returned.</remarks>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        /// <returns>True if any result from <c>predicate</c> is true.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when either of the input arrays is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input arrays differ in length.</exception>
        [<CompiledName("Exists2")>]
        val exists2: predicate:('T1 -> 'T2 -> bool) -> array1:'T1[] -> array2:'T2[] -> bool

        /// <summary>Returns a new collection containing only the elements of the collection
        /// for which the given predicate returns "true".</summary>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <returns>An array containing the elements for which the given predicate returns true.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Filter")>]
        val filter: predicate:('T -> bool) -> array:'T[] -> 'T[]

        /// <summary>Returns the first element for which the given function returns 'true'.
        /// Raise <c>KeyNotFoundException</c> if no such element exists.</summary>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.Collections.Generic.KeyNotFoundException">Thrown if <c>predicate</c>
        /// never returns true.</exception>
        /// <returns>The first element for which <c>predicate</c> returns true.</returns>
        [<CompiledName("Find")>]
        val find: predicate:('T -> bool) -> array:'T[] -> 'T

        /// <summary>Returns the last element for which the given function returns 'true'.
        /// Raise <c>KeyNotFoundException</c> if no such element exists.</summary>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.Collections.Generic.KeyNotFoundException">Thrown if <c>predicate</c>
        /// never returns true.</exception>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <returns>The last element for which <c>predicate</c> returns true.</returns>
        [<CompiledName("FindBack")>]
        val findBack: predicate:('T -> bool) -> array:'T[] -> 'T

        /// <summary>Returns the index of the first element in the array
        /// that satisfies the given predicate. Raise <c>KeyNotFoundException</c> if 
        /// none of the elements satisfy the predicate.</summary>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.Collections.Generic.KeyNotFoundException">Thrown if <c>predicate</c>
        /// never returns true.</exception>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <returns>The index of the first element in the array that satisfies the given predicate.</returns>
        [<CompiledName("FindIndex")>]
        val findIndex: predicate:('T -> bool) -> array:'T[] -> int

        /// <summary>Returns the index of the last element in the array
        /// that satisfies the given predicate. Raise <c>KeyNotFoundException</c> if
        /// none of the elements satisfy the predicate.</summary>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.Collections.Generic.KeyNotFoundException">Thrown if <c>predicate</c>
        /// never returns true.</exception>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <returns>The index of the last element in the array that satisfies the given predicate.</returns>
        [<CompiledName("FindIndexBack")>]
        val findIndexBack: predicate:('T -> bool) -> array:'T[] -> int

        /// <summary>Tests if all elements of the array satisfy the given predicate.</summary>
        ///
        /// <remarks>The predicate is applied to the elements of the input collection. If any application 
        /// returns false then the overall result is false and no further elements are tested. 
        /// Otherwise, true is returned.</remarks>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <returns>True if all of the array elements satisfy the predicate.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("ForAll")>]
        val forall: predicate:('T -> bool) -> array:'T[] -> bool


        /// <summary>Tests if all corresponding elements of the array satisfy the given predicate pairwise.</summary>
        ///
        /// <remarks>The predicate is applied to matching elements in the two collections up to the lesser of the 
        /// two lengths of the collections. If any application returns false then the overall result is 
        /// false and no further elements are tested. Otherwise, if one collection is longer 
        /// than the other then the <c>ArgumentException</c> exception is raised. 
        /// Otherwise, true is returned.</remarks>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when either of the input arrays is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input arrays differ in length.</exception>
        /// <returns>True if all of the array elements satisfy the predicate.</returns>
        [<CompiledName("ForAll2")>]
        val forall2: predicate:('T1 -> 'T2 -> bool) -> array1:'T1[] -> array2:'T2[] -> bool

        /// <summary>Applies a function to each element of the collection, threading an accumulator argument
        /// through the computation. If the input function is <c>f</c> and the elements are <c>i0...iN</c> then computes 
        /// <c>f (... (f s i0)...) iN</c></summary>
        /// <param name="folder">The function to update the state given the input elements.</param>
        /// <param name="state">The initial state.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The final state.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Fold")>]
        val fold<'T,'State> : folder:('State -> 'T -> 'State) -> state:'State -> array: 'T[] -> 'State

        /// <summary>Applies a function to each element of the array, starting from the end, threading an accumulator argument
        /// through the computation. If the input function is <c>f</c> and the elements are <c>i0...iN</c> then computes 
        /// <c>f i0 (...(f iN s))</c></summary>
        /// <param name="folder">The function to update the state given the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <param name="state">The initial state.</param>
        /// <returns>The state object after the folding function is applied to each element of the array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("FoldBack")>]
        val foldBack<'T,'State> : folder:('T -> 'State -> 'State) -> array:'T[] -> state:'State -> 'State

        /// <summary>Applies a function to pairs of elements drawn from the two collections, 
        /// left-to-right, threading an accumulator argument
        /// through the computation. The two input
        /// arrays must have the same lengths, otherwise an <c>ArgumentException</c> is
        /// raised.</summary>
        /// <param name="folder">The function to update the state given the input elements.</param>
        /// <param name="state">The initial state.</param>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when either of the input arrays is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input arrays differ in length.</exception>
        /// <returns>The final state.</returns>
        [<CompiledName("Fold2")>]
        val fold2<'T1,'T2,'State>  : folder:('State -> 'T1 -> 'T2 -> 'State) -> state:'State -> array1:'T1[] -> array2:'T2[] -> 'State

        /// <summary>Apply a function to pairs of elements drawn from the two collections, right-to-left, 
        /// threading an accumulator argument through the computation. The two input
        /// arrays must have the same lengths, otherwise an <c>ArgumentException</c> is
        /// raised.</summary>
        /// <param name="folder">The function to update the state given the input elements.</param>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        /// <param name="state">The initial state.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when either of the input arrays is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input arrays differ in length.</exception>
        /// <returns>The final state.</returns>
        [<CompiledName("FoldBack2")>]
        val foldBack2<'T1,'T2,'State> : folder:('T1 -> 'T2 -> 'State -> 'State) -> array1:'T1[] -> array2:'T2[] -> state:'State -> 'State

        /// <summary>Gets an element from an array.</summary>
        /// <param name="array">The input array.</param>
        /// <param name="index">The input index.</param>
        /// <returns>The value of the array at the given index.</returns>
        /// <exception cref="System.NullReferenceException">Thrown when the input array is null.</exception>
        /// <exception cref="System.IndexOutOfRangeException">Thrown when the index is negative or the input array does not contain enough elements.</exception>
        [<CompiledName("Get")>]
        val get: array:'T[] -> index:int -> 'T

        /// <summary>Returns the first element of the array.</summary>
        ///
        /// <param name="array">The input array.</param>
        ///
        /// <returns>The first element of the array.</returns>
        ///
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input array is empty.</exception>
        [<CompiledName("Head")>]
        val head: array:'T[] -> 'T

        /// <summary>Applies a key-generating function to each element of an array and yields an array of 
        /// unique keys. Each unique key contains an array of all elements that match 
        /// to this key.</summary>
        ///
        /// <param name="projection">A function that transforms an element of the array into a comparable key.</param>
        /// <param name="array">The input array.</param>
        ///
        /// <returns>The result array.</returns>
        ///
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("GroupBy")>]
        val groupBy : projection:('T -> 'Key) -> array:'T[] -> ('Key * 'T[])[]  when 'Key : equality

        /// <summary>Builds a new array whose elements are the corresponding elements of the input array
        /// paired with the integer index (from 0) of each element.</summary>
        /// <param name="array">The input array.</param>
        /// <returns>The array of indexed elements.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Indexed")>]
        val indexed: array:'T[] -> (int * 'T)[]

        /// <summary>Creates an array given the dimension and a generator function to compute the elements.</summary>
        /// <param name="count">The number of elements to initialize.</param>
        /// <param name="initializer">The function to generate the initial values for each index.</param>
        /// <returns>The created array.</returns>
        /// <exception cref="System.ArgumentException">Thrown when count is negative.</exception>
        [<CompiledName("Initialize")>]
        val inline init: count:int -> initializer:(int -> 'T) -> 'T[]

        /// <summary>Creates an array where the entries are initially the default value Unchecked.defaultof&lt;'T&gt;.</summary>
        /// <param name="count">The length of the array to create.</param>
        /// <returns>The created array.</returns>
        /// <exception cref="System.ArgumentException">Thrown when count is negative.</exception>
        [<CompiledName("ZeroCreate")>]
        val zeroCreate: count:int -> 'T[]
         
        /// <summary>Returns true if the given array is empty, otherwise false.</summary>
        /// <param name="array">The input array.</param>
        /// <returns>True if the array is empty.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("IsEmpty")>]
        val isEmpty: array:'T[] -> bool

        /// <summary>Applies the given function to each element of the array.</summary>
        /// <param name="action">The function to apply.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Iterate")>]
        val inline iter: action:('T -> unit) -> array:'T[] -> unit

        /// <summary>Applies the given function to pair of elements drawn from matching indices in two arrays. The
        /// two arrays must have the same lengths, otherwise an <c>ArgumentException</c> is
        /// raised.</summary>
        /// <param name="action">The function to apply.</param>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when either of the input arrays is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input arrays differ in length.</exception>
        [<CompiledName("Iterate2")>]
        val iter2: action:('T1 -> 'T2 -> unit) -> array1:'T1[] -> array2:'T2[] -> unit

        /// <summary>Applies the given function to each element of the array. The integer passed to the
        /// function indicates the index of element.</summary>
        /// <param name="action">The function to apply to each index and element.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("IterateIndexed")>]
        val iteri: action:(int -> 'T -> unit) -> array:'T[] -> unit

        /// <summary>Applies the given function to pair of elements drawn from matching indices in two arrays,
        /// also passing the index of the elements. The two arrays must have the same lengths, 
        /// otherwise an <c>ArgumentException</c> is raised.</summary>
        /// <param name="action">The function to apply to each index and pair of elements.</param>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when either of the input arrays is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input arrays differ in length.</exception>
        [<CompiledName("IterateIndexed2")>]
        val iteri2: action:(int -> 'T1 -> 'T2 -> unit) -> array1:'T1[] -> array2:'T2[] -> unit

        /// <summary>Returns the last element of the array.</summary>
        /// <param name="array">The input array.</param>
        /// <returns>The last element of the array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input does not have any elements.</exception>
        [<CompiledName("Last")>]
        val inline last: array:'T[] -> 'T

        /// <summary>Gets an element from an array.</summary>
        /// <param name="index">The input index.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The value of the array at the given index.</returns>
        /// <exception cref="System.NullReferenceException">Thrown when the input array is null.</exception>
        /// <exception cref="System.IndexOutOfRangeException">Thrown when the index is negative or the input array does not contain enough elements.</exception>
        [<CompiledName("Item")>]
        val item: index:int -> array:'T[] -> 'T

        /// <summary>Returns the length of an array. You can also use property arr.Length.</summary>
        /// <param name="array">The input array.</param>
        /// <returns>The length of the array.</returns>
        /// <exception cref="System.NullReferenceException">Thrown when the input array is null.</exception>
        [<CompiledName("Length")>]
        val length: array:'T[] -> int
        
        /// <summary>Returns the last element of the array.
        /// Return <c>None</c> if no such element exists.</summary>
        /// <param name="array">The input array.</param>
        /// <returns>The last element of the array or None.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input sequence is null.</exception> 
        [<CompiledName("TryLast")>]
        val tryLast: array:'T[] -> 'T option

        /// <summary>Builds a new array whose elements are the results of applying the given function
        /// to each of the elements of the array.</summary>
        /// <param name="mapping">The function to transform elements of the array.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The array of transformed elements.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Map")>]
        val inline map: mapping:('T -> 'U) -> array:'T[] -> 'U[]

        /// <summary>Builds a new collection whose elements are the results of applying the given function
        /// to the corresponding elements of the two collections pairwise. The two input
        /// arrays must have the same lengths, otherwise an <c>ArgumentException</c> is
        /// raised.</summary>
        /// <param name="mapping">The function to transform the pairs of the input elements.</param>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        /// <exception cref="System.ArgumentException">Thrown when the input arrays differ in length.</exception>
        /// <exception cref="System.ArgumentNullException">Thrown when either of the input arrays is null.</exception>
        /// <returns>The array of transformed elements.</returns>
        [<CompiledName("Map2")>]
        val map2: mapping:('T1 -> 'T2 -> 'U) -> array1:'T1[] -> array2:'T2[] -> 'U[]

        /// <summary>Combines map and fold. Builds a new array whose elements are the results of applying the given function
        /// to each of the elements of the input array. The function is also used to accumulate a final value.</summary>
        /// <param name="mapping">The function to transform elements from the input array and accumulate the final value.</param>
        /// <param name="state">The initial state.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <returns>The array of transformed elements, and the final accumulated value.</returns>
        [<CompiledName("MapFold")>]
        val mapFold<'T,'State,'Result> : mapping:('State -> 'T -> 'Result * 'State) -> state:'State -> array:'T[] -> 'Result[] * 'State

        /// <summary>Combines map and foldBack. Builds a new array whose elements are the results of applying the given function
        /// to each of the elements of the input array. The function is also used to accumulate a final value.</summary>
        /// <param name="mapping">The function to transform elements from the input array and accumulate the final value.</param>
        /// <param name="array">The input array.</param>
        /// <param name="state">The initial state.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <returns>The array of transformed elements, and the final accumulated value.</returns>
        [<CompiledName("MapFoldBack")>]
        val mapFoldBack<'T,'State,'Result> : mapping:('T -> 'State -> 'Result * 'State) -> array:'T[] -> state:'State -> 'Result[] * 'State

        /// <summary>Builds a new collection whose elements are the results of applying the given function
        /// to the corresponding triples from the three collections. The three input
        /// arrays must have the same length, otherwise an <c>ArgumentException</c> is
        /// raised.</summary>
        /// <param name="mapping">The function to transform the pairs of the input elements.</param>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        /// <param name="array3">The third input array.</param>
        /// <exception cref="System.ArgumentException">Thrown when the input arrays differ in length.</exception>
        /// <exception cref="System.ArgumentNullException">Thrown when any of the input arrays is null.</exception>
        /// <returns>The array of transformed elements.</returns>
        [<CompiledName("Map3")>]
        val map3: mapping:('T1 -> 'T2 -> 'T3 -> 'U) -> array1:'T1[] -> array2:'T2[] -> array3:'T3[] -> 'U[]

        /// <summary>Builds a new collection whose elements are the results of applying the given function
        /// to the corresponding elements of the two collections pairwise, also passing the index of 
        /// the elements. The two input arrays must have the same lengths, otherwise an <c>ArgumentException</c> is
        /// raised.</summary>
        /// <param name="mapping">The function to transform pairs of input elements and their indices.</param>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when either of the input arrays is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input arrays differ in length.</exception>
        /// <returns>The array of transformed elements.</returns>
        [<CompiledName("MapIndexed2")>]
        val mapi2: mapping:(int -> 'T1 -> 'T2 -> 'U) -> array1:'T1[] -> array2:'T2[] -> 'U[]

        /// <summary>Builds a new array whose elements are the results of applying the given function
        /// to each of the elements of the array. The integer index passed to the
        /// function indicates the index of element being transformed.</summary>
        /// <param name="mapping">The function to transform elements and their indices.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The array of transformed elements.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("MapIndexed")>]
        val mapi: mapping:(int -> 'T -> 'U) -> array:'T[] -> 'U[]

        /// <summary>Returns the greatest of all elements of the array, compared via Operators.max on the function result.</summary>
        ///
        /// <remarks>Throws ArgumentException for empty arrays.</remarks>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input array is empty.</exception>
        /// <returns>The maximum element.</returns>
        [<CompiledName("Max")>]
        val inline max     : array:'T[] -> 'T  when 'T : comparison 

        /// <summary>Returns the greatest of all elements of the array, compared via Operators.max on the function result.</summary>
        ///
        /// <remarks>Throws ArgumentException for empty arrays.</remarks>
        /// <param name="projection">The function to transform the elements into a type supporting comparison.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input array is empty.</exception>
        /// <returns>The maximum element.</returns>
        [<CompiledName("MaxBy")>]
        val inline maxBy  : projection:('T -> 'U) -> array:'T[] -> 'T when 'U : comparison 

        /// <summary>Returns the lowest of all elements of the array, compared via Operators.min.</summary>
        ///
        /// <remarks>Throws ArgumentException for empty arrays</remarks>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input array is empty.</exception>
        /// <returns>The minimum element.</returns>
        [<CompiledName("Min")>]
        val inline min     : array:'T[] -> 'T  when 'T : comparison 

        /// <summary>Returns the lowest of all elements of the array, compared via Operators.min on the function result.</summary>
        ///
        /// <remarks>Throws ArgumentException for empty arrays.</remarks>
        /// <param name="projection">The function to transform the elements into a type supporting comparison.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input array is empty.</exception>
        /// <returns>The minimum element.</returns>
        [<CompiledName("MinBy")>]
        val inline minBy  : projection:('T -> 'U) -> array:'T[] -> 'T when 'U : comparison 

        /// <summary>Builds an array from the given list.</summary>
        /// <param name="list">The input list.</param>
        /// <returns>The array of elements from the list.</returns>
        [<CompiledName("OfList")>]
        val ofList: list:'T list -> 'T[]

        /// <summary>Builds a new array from the given enumerable object.</summary>
        /// <param name="source">The input sequence.</param>
        /// <returns>The array of elements from the sequence.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input sequence is null.</exception>
        [<CompiledName("OfSeq")>]
        val ofSeq: source:seq<'T> -> 'T[]

        /// <summary>Returns an array of each element in the input array and its predecessor, with the
        /// exception of the first element which is only returned as the predecessor of the second element.</summary>
        ///
        /// <param name="array">The input array.</param>
        ///
        /// <returns>The result array.</returns>
        ///
        /// <exception cref="System.ArgumentNullException">Thrown when the input sequence is null.</exception>
        [<CompiledName("Pairwise")>]
        val pairwise: array:'T[] -> ('T * 'T)[]

        /// <summary>Splits the collection into two collections, containing the 
        /// elements for which the given predicate returns "true" and "false"
        /// respectively.</summary>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <returns>A pair of arrays. The first containing the elements the predicate evaluated to true,
        /// and the second containing those evaluated to false.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Partition")>]
        val partition: predicate:('T -> bool) -> array:'T[] -> 'T[] * 'T[]

        /// <summary>Returns an array with all elements permuted according to the
        /// specified permutation.</summary>
        /// <param name="indexMap">The function that maps input indices to output indices.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The output array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when indexMap does not produce a valid permutation.</exception>
        [<CompiledName("Permute")>]
        val permute : indexMap:(int -> int) -> array:'T[] -> 'T[]

        /// <summary>Applies a function to each element of the array, threading an accumulator argument
        /// through the computation. If the input function is <c>f</c> and the elements are <c>i0...iN</c> 
        /// then computes <c>f (... (f i0 i1)...) iN</c>.
        /// Raises ArgumentException if the array has size zero.</summary>
        /// <param name="reduction">The function to reduce a pair of elements to a single element.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input array is empty.</exception>
        /// <returns>The final result of the reductions.</returns>
        [<CompiledName("Reduce")>]
        val reduce: reduction:('T -> 'T -> 'T) -> array:'T[] -> 'T

        /// <summary>Applies a function to each element of the array, starting from the end, threading an accumulator argument
        /// through the computation. If the input function is <c>f</c> and the elements are <c>i0...iN</c> 
        /// then computes <c>f i0 (...(f iN-1 iN))</c>.</summary>
        /// <param name="reduction">A function that takes in the next-to-last element of the list and the
        /// current accumulated result to produce the next accumulated result.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input array is empty.</exception>
        /// <returns>The final result of the reductions.</returns>
        [<CompiledName("ReduceBack")>]
        val reduceBack: reduction:('T -> 'T -> 'T) -> array:'T[] -> 'T

        /// <summary>Creates an array by replicating the given initial value.</summary>
        /// <param name="count">The number of elements to replicate.</param>
        /// <param name="initial">The value to replicate</param>
        /// <returns>The generated array.</returns>
        /// <exception cref="System.ArgumentException">Thrown when count is negative.</exception>
        [<CompiledName("Replicate")>]
        val replicate: count:int -> initial:'T -> 'T[]

        /// <summary>Returns a new array with the elements in reverse order.</summary>
        /// <param name="array">The input array.</param>
        /// <returns>The reversed array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Reverse")>]
        val rev: array:'T[] -> 'T[]

        /// <summary>Like <c>fold</c>, but return the intermediary and final results.</summary>
        /// <param name="folder">The function to update the state given the input elements.</param>
        /// <param name="state">The initial state.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The array of state values.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Scan")>]
        val scan<'T,'State> : folder:('State -> 'T -> 'State) -> state:'State -> array:'T[] -> 'State[]

        /// <summary>Like <c>foldBack</c>, but return both the intermediary and final results.</summary>
        /// <param name="folder">The function to update the state given the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <param name="state">The initial state.</param>
        /// <returns>The array of state values.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("ScanBack")>]
        val scanBack<'T,'State> : folder:('T -> 'State -> 'State) -> array:'T[] -> state:'State -> 'State[]

        /// <summary>Returns an array that contains one item only.</summary>
        ///
        /// <param name="value">The input item.</param>
        ///
        /// <returns>The result array of one item.</returns>
        [<CompiledName("Singleton")>]
        val inline singleton: value:'T -> 'T[]

        /// <summary>Sets an element of an array.</summary>
        /// <param name="array">The input array.</param>
        /// <param name="index">The input index.</param>
        /// <param name="value">The input value.</param>
        /// <exception cref="System.NullReferenceException">Thrown when the input array is null.</exception>
        /// <exception cref="System.IndexOutOfRangeException">Thrown when the index is negative or the input array does not contain enough elements.</exception>
        [<CompiledName("Set")>]
        val set: array:'T[] -> index:int -> value:'T -> unit

        /// <summary>Builds a new array that contains the elements of the given array, excluding the first N elements.</summary>
        /// <param name="count">The number of elements to skip.</param>
        /// <param name="array">The input array.</param>
        /// <returns>A copy of the input array, after removing the first N elements.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentExcepion">Thrown when count is negative or exceeds the number of 
        /// elements in the array.</exception>
        [<CompiledName("Skip")>]
        val skip: count:int -> array:'T[] -> 'T[]

        /// <summary>Bypasses elements in an array while the given predicate returns True, and then returns
        /// the remaining elements in a new array.</summary>
        /// <param name="predicate">A function that evaluates an element of the array to a boolean value.</param>
        /// <param name="source">The input array.</param>
        /// <returns>The created sub array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("SkipWhile")>]
        val skipWhile: predicate:('T -> bool) -> array:'T[] -> 'T[]

        /// <summary>Builds a new array that contains the given subrange specified by
        /// starting index and length.</summary>
        /// <param name="array">The input array.</param>
        /// <param name="startIndex">The index of the first element of the sub array.</param>
        /// <param name="count">The length of the sub array.</param>
        /// <returns>The created sub array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when either startIndex or count is negative,
        /// or when there aren't enough elements in the input array.</exception>
        [<CompiledName("GetSubArray")>]
        val sub: array:'T[] -> startIndex:int -> count:int -> 'T[]

        /// <summary>Sorts the elements of an array, returning a new array. Elements are compared using Operators.compare. </summary>
        ///
        /// <remarks>This is not a stable sort, i.e. the original order of equal elements is not necessarily preserved. 
        /// For a stable sort, consider using Seq.sort.</remarks>
        /// <param name="array">The input array.</param>
        /// <returns>The sorted array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Sort")>]
        val sort: array:'T[] -> 'T[] when 'T : comparison 

        /// <summary>Sorts the elements of an array, using the given projection for the keys and returning a new array. 
        /// Elements are compared using Operators.compare.</summary>
        ///
        /// <remarks>This is not a stable sort, i.e. the original order of equal elements is not necessarily preserved. 
        /// For a stable sort, consider using Seq.sort.</remarks>
        /// <param name="projection">The function to transform array elements into the type that is compared.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The sorted array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("SortBy")>]
        val sortBy: projection:('T -> 'Key) -> array:'T[] -> 'T[] when 'Key : comparison 

        /// <summary>Sorts the elements of an array, using the given comparison function as the order, returning a new array.</summary>
        ///
        /// <remarks>This is not a stable sort, i.e. the original order of equal elements is not necessarily preserved. 
        /// For a stable sort, consider using Seq.sort.</remarks>
        /// <param name="comparer">The function to compare pairs of array elements.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The sorted array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("SortWith")>]
        val sortWith: comparer:('T -> 'T -> int) -> array:'T[] -> 'T[]

        /// <summary>Sorts the elements of an array by mutating the array in-place, using the given projection for the keys. 
        /// Elements are compared using Operators.compare.</summary>
        ///
        /// <remarks>This is not a stable sort, i.e. the original order of equal elements is not necessarily preserved. 
        /// For a stable sort, consider using Seq.sort.</remarks>
        /// <param name="projection">The function to transform array elements into the type that is compared.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("SortInPlaceBy")>]
        val sortInPlaceBy: projection:('T -> 'Key) -> array:'T[] -> unit when 'Key : comparison 



        /// <summary>Sorts the elements of an array by mutating the array in-place, using the given comparison function as the order.</summary>
        /// <param name="comparer">The function to compare pairs of array elements.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("SortInPlaceWith")>]
        val sortInPlaceWith: comparer:('T -> 'T -> int) -> array:'T[] -> unit

        /// <summary>Sorts the elements of an array by mutating the array in-place, using the given comparison function. 
        /// Elements are compared using Operators.compare.</summary>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("SortInPlace")>]
        val sortInPlace: array:'T[] -> unit when 'T : comparison 

        /// <summary>Splits an array into two arrays, at the given index.</summary>
        /// <param name="index">The index at which the array is split.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The two split arrays.</returns>
        ///
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.InvalidOperationException">Thrown when split index exceeds the number of elements
        /// in the array.</exception>
        [<CompiledName("SplitAt")>]
        val splitAt: index:int -> array:'T[] -> ('T[] * 'T[])

        /// <summary>Sorts the elements of an array, in descending order, returning a new array. Elements are compared using Operators.compare. </summary>
        ///
        /// <remarks>This is not a stable sort, i.e. the original order of equal elements is not necessarily preserved. 
        /// For a stable sort, consider using Seq.sort.</remarks>
        /// <param name="array">The input array.</param>
        /// <returns>The sorted array.</returns>
        [<CompiledName("SortDescending")>]
        val inline sortDescending: array:'T[] -> 'T[] when 'T : comparison

        /// <summary>Sorts the elements of an array, in descending order, using the given projection for the keys and returning a new array. 
        /// Elements are compared using Operators.compare.</summary>
        ///
        /// <remarks>This is not a stable sort, i.e. the original order of equal elements is not necessarily preserved. 
        /// For a stable sort, consider using Seq.sort.</remarks>
        /// <param name="projection">The function to transform array elements into the type that is compared.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The sorted array.</returns>
        [<CompiledName("SortByDescending")>]
        val inline sortByDescending: projection:('T -> 'Key) -> array:'T[] -> 'T[] when 'Key : comparison

        /// <summary>Returns the sum of the elements in the array.</summary>
        /// <param name="array">The input array.</param>
        /// <returns>The resulting sum.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Sum")>]
        val inline sum   : array: ^T[] -> ^T 
                                when ^T : (static member ( + ) : ^T * ^T -> ^T) 
                                and  ^T : (static member Zero : ^T)


        /// <summary>Returns the sum of the results generated by applying the function to each element of the array.</summary>
        /// <param name="projection">The function to transform the array elements into the type to be summed.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The resulting sum.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("SumBy")>]
        val inline sumBy   : projection:('T -> ^U) -> array:'T[] -> ^U 
                                  when ^U : (static member ( + ) : ^U * ^U -> ^U) 
                                  and  ^U : (static member Zero : ^U)

        /// <summary>Returns the first N elements of the array.</summary>
        /// <remarks>Throws <c>InvalidOperationException</c>
        /// if the count exceeds the number of elements in the array. <c>Array.truncate</c>
        /// returns as many items as the array contains instead of throwing an exception.</remarks>
        ///
        /// <param name="count">The number of items to take.</param>
        /// <param name="array">The input array.</param>
        ///
        /// <returns>The result array.</returns>
        ///
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input array is empty.</exception>
        /// <exception cref="System.InvalidOperationException">Thrown when count exceeds the number of elements
        /// in the list.</exception>
        [<CompiledName("Take")>]
        val take: count:int -> array:'T[] -> 'T[]

        /// <summary>Returns an array that contains all elements of the original array while the 
        /// given predicate returns True, and then returns no further elements.</summary>
        ///
        /// <param name="predicate">A function that evaluates to false when no more items should be returned.</param>
        /// <param name="array">The input array.</param>
        ///
        /// <returns>The result array.</returns>
        ///
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("TakeWhile")>]
        val takeWhile: predicate:('T -> bool) -> array:'T[] -> 'T[]

        /// <summary>Returns a new array containing the elements of the original except the first element.</summary>
        ///
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentException">Thrown when the array is empty.</exception>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <returns>A new array containing the elements of the original except the first element.</returns>
        [<CompiledName("Tail")>]
        val tail: array:'T[] -> 'T[]

        /// <summary>Builds a list from the given array.</summary>
        /// <param name="array">The input array.</param>
        /// <returns>The list of array elements.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("ToList")>]
        val toList: array:'T[] -> 'T list

        /// <summary>Views the given array as a sequence.</summary>
        /// <param name="array">The input array.</param>
        /// <returns>The sequence of array elements.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("ToSeq")>]
        val toSeq: array:'T[] -> seq<'T>

        /// <summary>Returns at most N elements in a new array.</summary>
        /// <param name="count">The maximum number of items to return.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The result array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Truncate")>]
        val truncate: count:int -> array:'T[] -> 'T[]

        /// <summary>Returns the first element for which the given function returns True.
        /// Return None if no such element exists.</summary>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The first element that satisfies the predicate, or None.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("TryFind")>]
        val tryFind: predicate:('T -> bool) -> array:'T[] -> 'T option

        /// <summary>Returns the last element for which the given function returns True.
        /// Return None if no such element exists.</summary>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <returns>The last element that satisfies the predicate, or None.</returns>
        [<CompiledName("TryFindBack")>]
        val tryFindBack: predicate:('T -> bool) -> array:'T[] -> 'T option

        /// <summary>Returns the index of the first element in the array
        /// that satisfies the given predicate.</summary>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <returns>The index of the first element that satisfies the predicate, or None.</returns>
        [<CompiledName("TryFindIndex")>]
        val tryFindIndex : predicate:('T -> bool) -> array:'T[] -> int option

        /// <summary>Tries to find the nth element in the array.
        /// Returns <c>None</c> if index is negative or the input array does not contain enough elements.</summary>
        /// <param name="index">The index of element to retrieve.</param>
        /// <param name="source">The input array.</param>
        /// <returns>The nth element of the array or <c>None</c>.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("TryItem")>]
        val tryItem: index:int -> array:'T[] -> 'T option

        /// <summary>Returns the index of the last element in the array
        /// that satisfies the given predicate.</summary>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <returns>The index of the last element that satisfies the predicate, or None.</returns>
        [<CompiledName("TryFindIndexBack")>]
        val tryFindIndexBack : predicate:('T -> bool) -> array:'T[] -> int option

        /// <summary>Returns an array that contains the elements generated by the given computation.
        /// The given initial <c>state</c> argument is passed to the element generator.</summary>
        /// <param name="generator">A function that takes in the current state and returns an option tuple of the next
        /// element of the array and the next state value.</param>
        /// <param name="state">The initial state value.</param>
        /// <returns>The result array.</returns>
        [<CompiledName("Unfold")>]
        val unfold<'T,'State> : generator:('State -> ('T * 'State) option) -> state:'State -> 'T[]

        /// <summary>Splits an array of pairs into two arrays.</summary>
        /// <param name="array">The input array.</param>
        /// <returns>The two arrays.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Unzip")>]
        val unzip: array:('T1 * 'T2)[] -> ('T1[] * 'T2[])

        /// <summary>Splits an array of triples into three arrays.</summary>
        /// <param name="array">The input array.</param>
        /// <returns>The tuple of three arrays.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Unzip3")>]
        val unzip3: array:('T1 * 'T2 * 'T3)[] -> ('T1[] * 'T2[] * 'T3[])

        /// <summary>Returns a new array containing only the elements of the array
        /// for which the given predicate returns "true".</summary>
        /// <param name="predicate">The function to test the input elements.</param>
        /// <param name="array">The input array.</param>
        /// <returns>An array containing the elements for which the given predicate returns true.</returns>
        ///
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        [<CompiledName("Where")>]
        val where: predicate:('T -> bool) -> array:'T[] -> 'T[]

        /// <summary>Returns an array of sliding windows containing elements drawn from the input
        /// array. Each window is returned as a fresh array.</summary>
        /// <param name="windowSize">The number of elements in each window.</param>
        /// <param name="array">The input array.</param>
        /// <returns>The result array.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when windowSize is not positive.</exception>
        [<CompiledName("Windowed")>]
        val windowed : windowSize:int -> array:'T[] -> 'T[][]

        /// <summary>Combines the two arrays into an array of pairs. The two arrays must have equal lengths, otherwise an <c>ArgumentException</c> is
        /// raised.</summary>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when either of the input arrays is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input arrays differ in length.</exception>
        /// <returns>The array of tupled elements.</returns>
        [<CompiledName("Zip")>]
        val zip: array1:'T1[] -> array2:'T2[] -> ('T1 * 'T2)[]

        /// <summary>Combines three arrays into an array of pairs. The three arrays must have equal lengths, otherwise an <c>ArgumentException</c> is
        /// raised.</summary>
        /// <param name="array1">The first input array.</param>
        /// <param name="array2">The second input array.</param>
        /// <param name="array3">The third input array.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when any of the input arrays are null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when the input arrays differ in length.</exception>
        /// <returns>The array of tupled elements.</returns>
        [<CompiledName("Zip3")>]
        val zip3: array1:'T1[] -> array2:'T2[] -> array3:'T3[] -> ('T1 * 'T2 * 'T3)[]

#if !FX_NO_TPL_PARALLEL
        /// <summary>Provides parallel operations on arrays </summary>
        module Parallel =

            /// <summary>Apply the given function to each element of the array. Return
            /// the array comprised of the results "x" for each element where
            /// the function returns Some(x).</summary>
            ///
            /// <remarks>Performs the operation in parallel using System.Threading.Parallel.For.
            /// The order in which the given function is applied to elements of the input array is not specified.</remarks>
            /// <param name="chooser">The function to generate options from the elements.</param>
            /// <param name="array">The input array.</param>
            /// <returns>'U[]</returns>
            /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
            [<CompiledName("Choose")>]
            val choose: chooser:('T -> 'U option) -> array:'T[] -> 'U[]

            /// <summary>For each element of the array, apply the given function. Concatenate all the results and return the combined array.</summary>
            ///
            /// <remarks>Performs the operation in parallel using System.Threading.Parallel.For.
            /// The order in which the given function is applied to elements of the input array is not specified.</remarks>
            /// <param name="mapping"></param>
            /// <param name="array">The input array.</param>
            /// <returns>'U[]</returns>
            /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
            [<CompiledName("Collect")>]
            val collect : mapping:('T -> 'U[]) -> array:'T[] -> 'U[]
            
            /// <summary>Build a new array whose elements are the results of applying the given function
            /// to each of the elements of the array.</summary>
            ///
            /// <remarks>Performs the operation in parallel using System.Threading.Parallel.For.
            /// The order in which the given function is applied to elements of the input array is not specified.</remarks>
            /// <param name="mapping"></param>
            /// <param name="array">The input array.</param>
            /// <returns>'U[]</returns>
            /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
            [<CompiledName("Map")>]
            val map : mapping:('T -> 'U) -> array:'T[] -> 'U[]
            
            /// <summary>Build a new array whose elements are the results of applying the given function
            /// to each of the elements of the array. The integer index passed to the
            /// function indicates the index of element being transformed.</summary>
            ///
            /// <remarks>Performs the operation in parallel using System.Threading.Parallel.For.
            /// The order in which the given function is applied to elements of the input array is not specified.</remarks>
            /// <param name="mapping"></param>
            /// <param name="array">The input array.</param>
            /// <returns>'U[]</returns>
            /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
            [<CompiledName("MapIndexed")>]
            val mapi: mapping:(int -> 'T -> 'U) -> array:'T[] -> 'U[]

            /// <summary>Apply the given function to each element of the array. </summary>
            ///
            /// <remarks>Performs the operation in parallel using System.Threading.Parallel.For.
            /// The order in which the given function is applied to elements of the input array is not specified.</remarks>
            /// <param name="action"></param>
            /// <param name="array">The input array.</param>
            /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
            [<CompiledName("Iterate")>]
            val iter : action:('T -> unit) -> array:'T[] -> unit

            /// <summary>Apply the given function to each element of the array. The integer passed to the
            /// function indicates the index of element.</summary>
            ///
            /// <remarks>Performs the operation in parallel using System.Threading.Parallel.For.
            /// The order in which the given function is applied to elements of the input array is not specified.</remarks>
            /// <param name="action"></param>
            /// <param name="array">The input array.</param>
            /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
            [<CompiledName("IterateIndexed")>]
            val iteri: action:(int -> 'T -> unit) -> array:'T[] -> unit
            
            /// <summary>Create an array given the dimension and a generator function to compute the elements.</summary>
            ///
            /// <remarks>Performs the operation in parallel using System.Threading.Parallel.For.
            /// The order in which the given function is applied to indices is not specified.</remarks>
            /// <param name="count"></param>
            /// <param name="initializer"></param>
            /// <returns>'T[]</returns>
            [<CompiledName("Initialize")>]
            val init : count:int -> initializer:(int -> 'T) -> 'T[]
            
            /// <summary>Split the collection into two collections, containing the 
            /// elements for which the given predicate returns "true" and "false"
            /// respectively </summary>
            ///
            /// <remarks>Performs the operation in parallel using System.Threading.Parallel.For.
            /// The order in which the given function is applied to indices is not specified.</remarks>
            /// <param name="predicate">The function to test the input elements.</param>
            /// <param name="array">The input array.</param>
            /// <returns>'T[] * 'T[]</returns>
            /// <exception cref="System.ArgumentNullException">Thrown when the input array is null.</exception>
            [<CompiledName("Partition")>]
            val partition : predicate:('T -> bool) -> array:'T[] -> 'T[] * 'T[]
#endif            
